package com.lab303.powerproject.service.impl;

import com.lab303.powerproject.entity.EnergyType;
import com.lab303.powerproject.entity.GraphInfo;
import com.lab303.powerproject.entity.Relationship;
import com.lab303.powerproject.pojo.CustomAtlasDevice;
import com.lab303.powerproject.pojo.CustomDevice;
import com.lab303.powerproject.pojo.CustomRelationship;
import com.lab303.powerproject.pojo.CustomRelationshipObject;
import com.lab303.powerproject.repository.DeviceRepository;
import com.lab303.powerproject.repository.EnergyTypeRepository;
import com.lab303.powerproject.repository.GraphInfoRepository;
import com.lab303.powerproject.repository.RelationshipRepository;
import com.lab303.powerproject.service.RelationshipService;
import com.lab303.powerproject.util.AdjustCoordinator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class RelationshipServiceImpl implements RelationshipService {

    @Autowired
    private RelationshipRepository relationshipRepository;
    @Autowired
    private DeviceRepository deviceRepository;

    @Autowired
    private EnergyTypeRepository energyTypeRepository;

    @Autowired
    private GraphInfoRepository graphInfoRepository;


    @Override
    public void saveRelationshipList(List list) {
        relationshipRepository.saveAll(list);
    }

    @Override
    public List findRelationshipByFrom(Integer deviceFrom) {
        List<Relationship> relationshipList = relationshipRepository.findRelationshipByFrom(deviceFrom);
        return relationshipList;
    }

    @Override
    public void deleteRelationshipById(Integer relId) {
        relationshipRepository.deleteById(relId);
    }
	
	 @Override
    public List findAllRelationship() {
        return relationshipRepository.findAll();
    }

     @Override
    public List findCustomRelationship(Integer deviceId) {
        List<CustomRelationship> customRelationships = relationshipRepository.findCustomRelationship(deviceId);
        for (CustomRelationship c:customRelationships){
            EnergyType energyType = energyTypeRepository.findById(c.getTypeId()).orElse(null);
            c.setTypeName(energyType.getTypeName());
        }
        return customRelationships;
    }

    @Override
    public List findCustomRelationshipList() {
        List<Relationship> list = relationshipRepository.findAll();
        List<CustomRelationshipObject> res = new ArrayList<>();
        for (Relationship relationship:list){
            CustomRelationshipObject object = new CustomRelationshipObject();
            Integer deviceFrom = relationship.getDeviceFrom();
            Integer deviceTo = relationship.getDeviceTo();
            int typeId = relationship.getTypeId();
            Integer graphId = relationship.getGraphId();
            object.setId(relationship.getId());
            object.setDeviceFrom(deviceFrom);
            object.setDeviceTo(deviceTo);
            object.setDeviceFromName(deviceRepository.selectCustomDevice(deviceFrom).getDeviceName());
            object.setDeviceToName(deviceRepository.selectCustomDevice(deviceTo).getDeviceName());
            object.setLossRate(relationship.getLossRate());
            object.setTypeId(typeId);
            object.setTypeName(energyTypeRepository.findById(typeId).get().getTypeName());
            object.setGraphId(graphId);
            object.setGraphName(graphInfoRepository.findById(graphId).get().getGraphName());
            object.setIsShard(relationship.getIsShard());
            object.setStgyCode(relationship.getStgyCode());
            object.setStgyType(relationship.getStgyType());
            res.add(object);
        }
        return res;
    }

    @Override
    public List<Map> getAllEdge(){
        List<Relationship> relationshipList = relationshipRepository.findAll();
        List<CustomAtlasDevice> customAtlasDevices = deviceRepository.selectAtlasDevice();
        return getEdge(relationshipList,customAtlasDevices);
    }

    @Override
    public List<Map> getEdgeByGraphId(Integer graphId) {
        List<Relationship> relationships = relationshipRepository.findRelationshipsByGraphIdEquals(graphId);
        List<CustomAtlasDevice> customAtlasDevices = deviceRepository.selectAtlasDeviceByGraphId(graphId);
        List<Map> edge = getEdge(relationships, customAtlasDevices);
        return edge;
    }

    private List<Map> getEdge(List<Relationship> relationships,List<CustomAtlasDevice> customAtlasDevices) {
        List<Map> list = new ArrayList<>();
        Iterator<CustomAtlasDevice> customAtlasDeviceIterator = customAtlasDevices.iterator();
        Map<Integer,CustomAtlasDevice> deviceMap = new HashMap<>();
        while (customAtlasDeviceIterator.hasNext()){
            CustomAtlasDevice customAtlasDevice = customAtlasDeviceIterator.next();
            deviceMap.put(customAtlasDevice.getDeviceId(),customAtlasDevice);
        }
        double length = AdjustCoordinator.getLength(customAtlasDevices);
        Iterator<Relationship> iterator = relationships.iterator();
        while (iterator.hasNext()){
            Relationship relationship = iterator.next();
            Map map = new HashMap();
            CustomAtlasDevice fromDevice = deviceMap.get(relationship.getDeviceFrom());
            CustomAtlasDevice toDevice = deviceMap.get(relationship.getDeviceTo());
            float[] fromCoordinate = fromDevice.getCoordinate();
            float[] toCoordinate = toDevice.getCoordinate();
            List adjustList = AdjustCoordinator.adjustByAngle(fromCoordinate[0], fromCoordinate[1], toCoordinate[0], toCoordinate[1], length,length+15,length+15);
            String str = fromDevice.getDeviceId()+"#"+toDevice.getDeviceId();
            EnergyType energyType = energyTypeRepository.findById(relationship.getTypeId()).get();
            map.put("line",adjustList);
            map.put("desc",str);
            map.put("energyPic",energyType.getIconPath());
            map.put("deviceName",Arrays.asList(fromDevice.getDeviceName(),toDevice.getDeviceName()));
            map.put("typeName",energyType.getTypeName());
            list.add(map);
        }
        return list;
    }

    @Override
    public List<CustomRelationshipObject> findCustomRelationshipListByGraphId(Integer graphId) {
        List<Relationship> list = relationshipRepository.findRelationshipsByGraphIdEquals(graphId);
        List<CustomRelationshipObject> res = new ArrayList<>();
        if(list!=null){

            for (Relationship relationship:list){
                CustomRelationshipObject object = new CustomRelationshipObject();
                Integer deviceFrom = relationship.getDeviceFrom();
                Integer deviceTo = relationship.getDeviceTo();
                int typeId = relationship.getTypeId();
                Integer graphId1 = relationship.getGraphId();
                object.setId(relationship.getId());
                object.setDeviceFrom(deviceFrom);
                object.setDeviceTo(deviceTo);
                object.setDeviceFromName(deviceRepository.selectCustomDevice(deviceFrom).getDeviceName());
                object.setDeviceToName(deviceRepository.selectCustomDevice(deviceTo).getDeviceName());
                object.setLossRate(relationship.getLossRate());
                object.setTypeId(typeId);
                object.setTypeName(energyTypeRepository.findById(typeId).get().getTypeName());
                object.setGraphId(graphId1);
                object.setGraphName(graphInfoRepository.findById(graphId).get().getGraphName());
                object.setIsShard(relationship.getIsShard());
                object.setStgyCode(relationship.getStgyCode());
                object.setStgyType(relationship.getStgyType());
                res.add(object);
            }

        }
        return res;
    }

    @Override
    public boolean checkDuplicateRelationship(Relationship relationship) {
        List<Relationship> list = relationshipRepository.findRelationshipsByDeviceFromAndAndDeviceToAndGraphId(relationship.getDeviceFrom(), relationship.getDeviceTo(),relationship.getGraphId());
        if (list==null||list.size()==0)
            return false;
        return true;
    }

    @Override
    public Relationship findRelationshipById(Integer id) {
        return relationshipRepository.findById(id).get();
    }

    @Override
    public Relationship updateRelationship(Relationship relationship) {
        Relationship save = relationshipRepository.save(relationship);
        return save;
    }

    @Override
    public Relationship findRelationshipByFromAndToAndGraphId(Relationship relationship) {
        List<Relationship> list = relationshipRepository.findRelationshipsByDeviceFromAndAndDeviceToAndGraphId(relationship.getDeviceFrom(), relationship.getDeviceTo(), relationship.getGraphId());
        return list==null||list.size()==0?null:list.get(0);
    }

    @Override
    public List getRelationshipListByGraphId(Integer graphId) {
        return relationshipRepository.findRelationshipsByGraphIdEquals(graphId);
    }

    @Override
    public void deleteRelationshipByGraphId(Integer graphId) {
        relationshipRepository.deleteRelationshipsByGraphId(graphId);
    }

    @Override
    public void deleteRelationshipOfDevice(Integer deviceId) {
        List<Relationship> deviceFromEquals = relationshipRepository.findRelationshipsByDeviceFromEquals(deviceId);
        List<Relationship> deviceToEquals = relationshipRepository.findRelationshipsByDeviceToEquals(deviceId);
        if (deviceFromEquals.size()>0){
            relationshipRepository.deleteInBatch(deviceFromEquals);
        }
        if (deviceToEquals.size()>0){
            relationshipRepository.deleteInBatch(deviceToEquals);
        }
    }

    @Override
    public boolean checkStgyCode(String stgyCode){
        List<Relationship> relationships = relationshipRepository.findRelationshipsByStgyCodeEquals(stgyCode);
        if(relationships == null || relationships.size() == 0){
            return true;
        }else {
            return false;
        }
    }

}
